#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "mrj_supt.h"

char** parse_cmd(char*);
void pcb_function(char*);
void create_pcb(char*);
void enqueueReady(pcb*);
pcb* searchPCBbyName(char*);
char* remove_ws(char*);
void removePCB(pcb*);
void enqueueBlocked(pcb*);
//pcb* setPCB(char*, int, int);


//pcb -setp [-127, 128]
void pcb_setp(char* argStr){
	char** argS = parse_cmd(argStr);
	char* pName = remove_ws(argS[0]);
	char* pStr = remove_ws(argS[1]);
	int new_priority=0;
	int nFlag=1;
	int n=0;
	int x;
	if(pStr[n]=='-'){
		nFlag=-1;
		n++;
	}
	for(x=0; n<strlen(pStr); x++){
		new_priority += ((int)(pStr[n])-48) * pow(10, x);
		n++;
	}
	new_priority *= nFlag;
	//Check to see if priority is valid; between -128 and 127
	if((new_priority < -128) || (new_priority > 127)){
		printf("ERROR: Process priority is invalid, please enter a value\nbetween -128 and 127\n");
	}
	else{
		pcb* pcbid = searchPCBbyName(pName);
		if(pcbid){
			pcbid->priority=(nFlag * new_priority);
			printf("%s: priority has been changed to %d.\n", pcbid->name, pcbid->priority);
		}
		else{
			printf("failed to set priority.\n");
		}
	}
}

void suspend_pcb(char* pName){
	pcb* pcbid = searchPCBbyName(pName);
	pcbid->susp=PCB_FLAG_SUSP;
	if(pcbid->susp){
		printf("%s is now suspended.\n");
	}
	else{
		printf("%s could not be suspended.\n");
	}
}

void resume_pcb(char* pName){
	pcb* pcbid = searchPCBbyName(pName);
	pcbid->susp=PCB_FLAG_FREE;
	if(pcbid->susp){
		printf("%s has resumed.\n");
	}
	else{
		printf("Error: %s could not resume.\n");
	}
}

void pcb_info(char* pName){
	pcb* pcbid = searchPCBbyName(pName);
	printf("name: %s\tstate: %d\tpriority: %d\n", pName, pcbid->state, pcbid->priority);
}

//pcb -blok pName
void block_pcb(char* pName){
	pcb* pcbid = searchPCBbyName(pName);
	pcbid->state = PCB_STATE_BLK;
	removePCB(pcbid);
	enqueueBlocked(pcbid);
}

void unblock_pcb(char* pName){
	pcb* pcbid = searchPCBbyName(pName);
	pcbid->state = PCB_STATE_RDY;
	removePCB(pcbid);
	enqueueReady(pcbid);
}
//pcb -del pName
void delete_pcb(char* pName){
	pcb* pcbid = searchPCBbyName(pName);
	removePCB(pcbid);
	if(!free_pcb(pcbid)){
		printf("pcb: %s successfully killed.\n", pName);
	}
	else{
		printf("unable to free pcb: %s\n", pName);
	}
	
}

//pcb -new pName (int)priority (int)class
void create_pcb(char* args){
	char pName[20]={'\0'};
	int priority=0;
	int pClass=0;
	int a=0;
	int nFlag=1;
	int pindex=0;
	int cindex=0;
	//copy the process name from cmd argument to new string
	while(!(args[a]==' ')||(args[a]=='\t')||(args[a]=='\n')){
		pName[a] = args[a];
		a++;
	}
	pName[a]='\0';
	//ignore ws
	while((args[a]==' ')||(args[a]=='\t')||(args[a]=='\n')){
		a++;
	}
	if(args[a]=='-'){
		nFlag=-1;
		a++;
	}
	//turn 2nd arg into int

	while(!(args[a]==' ')||(args[a]=='\t')||(args[a]=='\n')){
		priority += ((int)(args[a])-48)*pow(10, pindex);
		pindex++;
		a++;
	}
	//ignore ws
	while((args[a]==' ')||(args[a]=='\t')||(args[a]=='\n')){
		a++;
	}
	//turn 3rd arg into int

	while(!(args[a]==' ')||(args[a]=='\t')||(args[a]=='\n')){
		pClass += ((int)(args[a])-48)*pow(10, cindex);
		cindex++;
		a++;
	}
	priority *= nFlag;
	enqueueReady(setPCB(pName, priority, pClass));
}

//main argument handler for pcb controls
void pcb_function(char* pcbCmd){
	char** tokens = parse_cmd(pcbCmd);
	if(!strcmp(tokens[0], "-new")){
		create_pcb(tokens[1]);
	}
	else if(!strcmp(tokens[0], "-del")){
		delete_pcb(remove_ws(tokens[1]));
	}
	else if(!strcmp(tokens[0], "-blok")){
		block_pcb(remove_ws(tokens[1]));
	}
	else if(!strcmp(tokens[0], "-unblok")){
		unblock_pcb(remove_ws(tokens[1]));
	}
	else if(!strcmp(tokens[0], "-paus")){
		suspend_pcb(remove_ws(tokens[1]));
	}
	else if(!strcmp(tokens[0], "-play")){
		resume_pcb(remove_ws(tokens[1]));
	}
	else if(!strcmp(tokens[0], "-setp")){
		pcb_setp(tokens[1]);
	}
	else if(!strcmp(tokens[0], "-meta")){
		pcb_info(remove_ws(tokens[1]));
	}
	// else if(!strcmp(tokens[0], "-ready")){
		// disp_readyQ();
	// }
	// else if(!strcmp(tokens[0], "-blokked")){
		// disp_blockedQ();
	// }
	else{
		printf("\"%s\" is not a valid argument.\n", tokens[0]);
	}
	free(tokens[0]);
	free(tokens[1]);
	free(tokens);
}	
	